/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
 */

package com.jinhe.tss.component.dynproperty;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import com.jinhe.tss.component.dynproperty.entity.DynableEntity;
import com.jinhe.tss.component.dynproperty.entity.GridTemplate;
import com.jinhe.tss.component.dynproperty.entity.PropertyDef;
import com.jinhe.tss.component.dynproperty.entity.XFormTemplate;
import com.jinhe.tss.component.dynproperty.entity.XFormTemplateTab;
import com.jinhe.tss.component.support.web.webwork.PTActionSupport;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.web.dispaly.tree.ITreeTranslator;
import com.jinhe.tss.core.web.dispaly.tree.LevelTreeParser;
import com.jinhe.tss.core.web.dispaly.tree.TreeEncoder;
import com.jinhe.tss.core.web.dispaly.tree.TreeNode;
import com.jinhe.tss.core.web.dispaly.xform.IXForm;
import com.jinhe.tss.core.web.dispaly.xform.XFormEncoder;
 
public class PropertyAction extends PTActionSupport {

    private static final long serialVersionUID = -3331309268490849846L;
    
    private Long id;
    private Long parentId;
    private Long targetId;
    private int  direction;
    private String entityCode;
    private String entityName;
    
    private PropertyDef property = new PropertyDef();
    private DynableEntity entity = new DynableEntity();
    private File file;
    
    private XFormTemplate xTemplate = new XFormTemplate();
    private XFormTemplateTab tab = new XFormTemplateTab();
    private GridTemplate gTemplate = new GridTemplate();
    private String code;   
    
    private int type; //1: 动态实体组 2: 动态实体 3:属性 4:GridTemplate 5:XFormTemplate 6:XFormTemplateTab
    
    private PropertyService service;
    
    /*****************************************************************************************************
     ***************************************    基本的增删该维护   ******************************************
     ******************************************************************************************************/
    
    public String getObjectInfo(){
        XFormEncoder encoder = null;
        type = (type == 0 ? 3 : type);
        switch(type){
        case DynConstants.GROUP_TYPE:
        case DynConstants.ENTITY_TYPE:
            if(isCreateNew()){
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("parentId", parentId == null ? new Long(0) : parentId);
                encoder = new XFormEncoder(DynConstants.DYN_ENTITY_XFORM_TEMPLET_PATH, map);           
            } else {
                DynableEntity group = service.getGroupOrEntityById(id);            
                encoder = new XFormEncoder(DynConstants.DYN_ENTITY_XFORM_TEMPLET_PATH, (IXForm) group);
            }        
            return print("TreeInfo", encoder);
        case DynConstants.PROPERTY_TYPE:
            return getPropertyInfo();
        case DynConstants.GRID_TEMPLATE_TYPE: 
            if(isCreateNew()){
                Map<String, Object> map = new HashMap<String, Object>();
                DynableEntity entity = (DynableEntity) service.getEntity(DynableEntity.class, parentId);
                map.put("entityCode", entity.getEntityCode());
                encoder = new XFormEncoder(DynConstants.GRID_XFORM_TEMPLET_PATH, map);           
            }else{
                GridTemplate gTemplate = (GridTemplate) service.getEntity(GridTemplate.class, id);            
                encoder = new XFormEncoder(DynConstants.GRID_XFORM_TEMPLET_PATH, (IXForm) gTemplate);
            }        
            return print("TreeInfo", encoder);
        case DynConstants.XFORM_TEMPLATE_TYPE:
            if(isCreateNew()){
                Map<String, Object> map = new HashMap<String, Object>();
                DynableEntity entity = (DynableEntity) service.getEntity(DynableEntity.class, parentId);
                map.put("entityCode", entity.getEntityCode());
                encoder = new XFormEncoder(DynConstants.XFORM_XFORM_TEMPLET_PATH, map);           
            }else{
                XFormTemplate xTemplate = (XFormTemplate) service.getEntity(XFormTemplate.class, id);      
                encoder = new XFormEncoder(DynConstants.XFORM_XFORM_TEMPLET_PATH, (IXForm) xTemplate);
            }        
            return print("TreeInfo", encoder);
        case DynConstants.TAB_TYPE: 
            if(isCreateNew()){
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("xformTemplateId", parentId);
                encoder = new XFormEncoder(DynConstants.TAB_XFORM_TEMPLET_PATH, map);           
            }else{
                XFormTemplateTab tab = (XFormTemplateTab) service.getEntity(XFormTemplateTab.class, id);      
                encoder = new XFormEncoder(DynConstants.TAB_XFORM_TEMPLET_PATH, (IXForm) tab);
            }       
            return print("TreeInfo", encoder);
        }
        return XML;
    }
    
    public String saveObject(){
        boolean isNew = false;
        type = (type == 0 ? 3 : type);
        
        switch(type){
        case DynConstants.GROUP_TYPE:
            isNew = entity.getId() == null ? true : false;       
            entity = service.saveGroup(entity);
            return doAfterSave(isNew, entity, "DynamicPropertyTree");
        //case DynConstants.ENTITY_TYPE:  never 出现，动态实体只能通过导入的方式新增
        case DynConstants.PROPERTY_TYPE:
            return saveProperty();
        case DynConstants.GRID_TEMPLATE_TYPE: 
            isNew = gTemplate.getId() == null ? true : false;
            gTemplate = service.saveGridTemplate(gTemplate); //新增或修改一个Grid模板,只有code，name两项内容
            return doAfterSave(isNew, gTemplate, "DynamicPropertyTree");
        case DynConstants.XFORM_TEMPLATE_TYPE:
            isNew = xTemplate.getId() == null ? true : false;
            xTemplate = service.saveXFormTemplate(xTemplate); //新增或修改一个XForm模板,只有code，name两项内容
            return doAfterSave(isNew, xTemplate, "DynamicPropertyTree");
        case DynConstants.TAB_TYPE: 
            isNew = tab.getId() == null ? true : false;
            tab = service.saveXFormTemplateTab(tab);  //新增或修改一个XForm模板Tab页,只有code，name两项内容(修改布局时不针对单个tab页，修改的是一组表单).
            return doAfterSave(isNew, tab, "DynamicPropertyTree");
        default:
            return XML;
        }
    }
    /**
     * 根据类型删除对象
     * @return
     */
    public String removeObject(){
        type = (type == 0 ? 3 : type);
        switch(type){
        case DynConstants.PROPERTY_TYPE:
            service.deleteProperty(id); //移除一个动态属性，基本属性不允许删除。
            break;
        case DynConstants.GRID_TEMPLATE_TYPE:  
            service.deleteGridTemplate(id); //删除一个Grid模板包括其下所有的Tab页  
            break;
        case DynConstants.XFORM_TEMPLATE_TYPE:
            service.deleteXFormTemplate(id); //删除一个XForm模板包括其下所有的Tab页  
            break;
        case DynConstants.TAB_TYPE: 
            service.deleteXFormTemplateTab(id); //删除一个XForm模板Tab页  
            break;
        case DynConstants.GROUP_TYPE:
        case DynConstants.ENTITY_TYPE: 
        default:
            service.deleteGroupOrEntity(id); //移除一个动态实体或者动态实体组
            //如果是删除组，则重新刷新树。因为组下的实体及子组不会一并被删除，会默认放到根目录下。
            if(DynConstants.GROUP_TYPE == type)
                return print("script", "parent.loadInitData();alert(\"删除成功!!!\");");
            break;
        }
        return printSuccessMessage();
    }
    
    /**
     * 新增、查看或者修改一个动态属性
     * @return
     */
    private String getPropertyInfo(){
        XFormEncoder encoder = null;
        if(isCreateNew()){
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("entityCode", entityCode);
            map.put("entityName", entityName);
            map.put("allowNull", new Integer(1));
            encoder = new XFormEncoder(DynConstants.DYN_PROPERTY_XFORM_TEMPLET_PATH, map);           
        }else{
            PropertyDef info = service.getPropertyById(id);   
            if(info.isdyn()){
                encoder = new XFormEncoder(DynConstants.DYN_PROPERTY_XFORM_TEMPLET_PATH, (IXForm) info);     
            }else if(info.isSpare() || info.getKey().startsWith("spare")){
                encoder = new XFormEncoder(DynConstants.SPARE_PROPERTY_XFORM_TEMPLET_PATH, (IXForm) info);     
            }else{
                encoder = new XFormEncoder(DynConstants.BASE_PROPERTY_XFORM_TEMPLET_PATH, (IXForm) info);     
            }
        }       
        return print("DynamicPropertyInfo", encoder);
    }
    
    /**
     * 修改一个属性，或者新增一个动态属性。
     * @return
     */
    private String saveProperty(){
        boolean isNew = (property.getId() == null);       
        property = service.saveProperty(property);
        return doAfterSave(isNew, property, "DynamicPropertyTree", "动态属性已经修改，请重新编辑表单布局！");
    }
    
    /****************************************************************************************************/
    /****************************************************************************************************/
    /****************************************************************************************************/
    
    /**
     * 属性展示
     * @return
     */
    public String getDynableEntities4Tree(){
        List<?> entities = service.getDynableEntities(false);
        TreeEncoder encoder = new TreeEncoder(entities, new DynPropertyTreeParser());
        return print("DynamicPropertyTree", encoder);
    }
    
    public String getCanMoveToGroups4Tree(){
        List<?> canSeeGroups = service.getDynableEntities(true);
        List<?> targets = service.getCanMoveToGroups(id);
        
        final Long[] targetIds = new Long[targets.size()];
        for(int i = 0; i < targets.size(); i++){
            DynableEntity target = (DynableEntity) targets.get(i);
            targetIds[i] = target.getId();
        }
        
        TreeEncoder encoder = new TreeEncoder(canSeeGroups, new LevelTreeParser());
        encoder.setTranslator(new ITreeTranslator(){
            public Map<String, Object> translate(Map<String, Object> attributes) {
                Map<String, Object> map = new HashMap<String, Object>(attributes);
                if(Arrays.asList(targetIds).contains(map.get("id")) && !id.equals(map.get("id"))){
                    map.put(TreeNode.TREENODE_ATTRIBUTE_CANSELECTED, "1"); 
                }else{
                    map.put(TreeNode.TREENODE_ATTRIBUTE_CANSELECTED, "0"); 
                }                                  
                return map;
            }
        });
        encoder.setRootCanSelect(false);
        return print("SiteTree", encoder);
    }

    /**
     * 移动组或者动态实体到其他的组下
     * @return
     */
    public String moveGroupOrEntity(){
        targetId = targetId == null ? new Long(0) : targetId;
        service.moveGroupOrEntity(id, targetId);
        return printSuccessMessage();
    }
    
    public String getUploadForm(){
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("parentId", parentId == null ? new Long(0) : parentId);
        XFormEncoder encoder = new XFormEncoder(DynConstants.IMPORT_XFORM_TEMPLET_PATH, map);  
        
        return print("ImportEntity", encoder);
    }
    
    /**
     * 导入动态实体
     * @return
     */
    public String importDynableEntity(){
        if (null == file) {
            throw new BusinessException("导入文件为空！");
        }
        SAXReader reader = new SAXReader();
        Document document = null;
        try {
            document = reader.read(file);
            if(!document.getRootElement().getName().equals("class")){
                throw new BusinessException("xml文件根节点不是<class/>,导入文件可能不是规定的动态属性配置导入文件");
            }
        } catch (DocumentException e) {
            throw new BusinessException("导入文件可能不是规定的动态属性配置导入文件", e);
        }
        service.importDynableEntity(document.asXML(), parentId == null ? new Long(0) : parentId);
//        return print("script", "parent.loadInitData();alert(\"导入成功!!!\");var ws = parent.$(\"ws\");ws.closeActiveTab();");
        return print("script", "var response={};response.type='Success';response.msg='导入成功';response.description='导入成功';");
    }
    
    /**
     * 拷贝一个属性出来为动态属性
     * @return
     */
    public String copyProperty(){
        service.copyProperty(id);
        return printSuccessMessage();
    }
    /**
     * 将属性复制到其他的动态实体下做为动态属性
     * @return
     */
    public String copyPropertyTo(){
        service.copyPropertyTo(id, targetId);
        return XML;
    }
    /**
     * 属性排序
     * @return
     */
    public String sortProperty(){
        service.sortProperty(id, targetId, direction);
        return printSuccessMessage();
    }

    /****************************************************************************************************
     *********************************************  模板维护  ********************************************
     *****************************************************************************************************/
    /**
     * 获取某个动态对象实体所有的属性、某组XForm模板及其所有tab页信息。
     * 编辑xform模板布局的时候用。
     * @return
     */
    public String editXForm(){
        Object[] objs = service.getXFormTempalteInfo(entityCode, code);
        
        StringBuffer layoutBuf = new StringBuffer("<forms entityCode=\"");
        layoutBuf.append(entityCode).append("\">");        
        List<?> tabs = (List<?>) objs[0];
        if(tabs.isEmpty()) {
            throw new BusinessException("表单布局下必须包含至少一个表单页，请先创建表单页。");
        }
        
        for(Iterator<?> it = tabs.iterator(); it.hasNext();){
            XFormTemplateTab tab = (XFormTemplateTab) it.next();
            layoutBuf.append("<layout id=\"").append(tab.getId()).append("\" code=\"").append(tab.getCode());
            layoutBuf.append("\" name=\"").append(tab.getName()).append("\">");
            if(tab.getLayout() != null)
                layoutBuf.append(tab.getLayoutOnly());
            layoutBuf.append("</layout>");
        }
        layoutBuf.append("</forms>");
        
        StringBuffer columnBuf = new StringBuffer("<declare>");
        for(Iterator<?> it = ((List<?>) objs[1]).iterator(); it.hasNext();){
            PropertyDef property = (PropertyDef) it.next();
            if(!property.isHidden() && !property.isSpare()){ //非隐藏项传到前台
                columnBuf.append(property.genColumn());
            }                
        }
        columnBuf.append("</declare>");
        return print(new String[]{"FormLayout", "ColumnList"}, new Object[]{layoutBuf, columnBuf});
    } 
    
    private String layoutStr;
    
    /**
     * 保存表单布局。多个tab页分开编辑，但一起保存.
     * 编辑表单后，保存XForm模板declare节点（方法中需生成）和layout节点信息，并记录实体属性值保存到了哪个tab中.
     */
    public String saveXForm(){
        service.saveXForm(layoutStr);
        return printSuccessMessage("布局已经保存成功！");
    }
  
    /**
     * 获取某个指定的Grid模板,编辑grid列表模板的时候用。
     * @param entityCode
     * @param templateCode
     *               模板code
     * @return 
     */
    public String editGrid(){
        String columnList = service.getGridTemplateInfo(entityCode, code);
        GridTemplate gt = service.getGridTemplateByCode(entityCode, code);
        String layout = gt.getDeclare() != null ? gt.getDeclare() : columnList;
        String requiredProperties = gt.getRequiredProperties() != null ? gt.getRequiredProperties() : "";
        return print(new String[]{"ListLayout", "ColumnList", "RequiredProperties"}, new Object[]{layout, columnList, requiredProperties});
    }
    /**
     * 保存Grid布局
     */
    public String saveGrid(){
        GridTemplate t = (GridTemplate) service.getEntity(GridTemplate.class, id);
        t.setDeclare(layoutStr);
        service.saveGridTemplate(t);
        return printSuccessMessage();
    }
    
    /****************************************************************************************************
     ************************************************  End  *********************************************
     *****************************************************************************************************/ 
 
    public PropertyDef getProperty() {
        return property;
    }
 
    public void setEntityCode(String entityCode) {
        this.entityCode = entityCode;
    }
 
    public void setService(PropertyService service) {
        this.service = service;
    }
 
    public void setDirection(int direction) {
        this.direction = direction;
    }
 
    public void setTargetId(Long targetId) {
        this.targetId = targetId;
    }
 
    public void setFile(File file) {
        this.file = file;
    }
 
    public void setCode(String code) {
        this.code = code;
    }
 
    public void setEntityName(String entityName) {
        this.entityName = entityName;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public void setType(int type) {
        this.type = type;
    }
 
    public DynableEntity getEntity() {
        return entity;
    }
 
    public GridTemplate getGTemplate() {
        return gTemplate;
    }
 
    public XFormTemplateTab getTab() {
        return tab;
    }
 
    public XFormTemplate getXTemplate() {
        return xTemplate;
    }
 
    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }
 
    public void setLayoutStr(String layoutStr) {
        this.layoutStr = layoutStr;
    }
}